<?php
namespace App\Common\Server\Api\Gateway\Ext;

use App\Common as com;
use App as nameApp;
use App\Common\Server\Api as nameApi;
use App\Common\Server\Api\Gateway as nameGateway;
// use Hyperf\HttpServer\Analyse;
use Hyperf\HttpServer\Contract\RequestInterface;

class WebApi extends nameApi\Gateway {

	/**
	 * @var RequestInterface|null
	 */
	private RequestInterface|null $request = null;

	/**
	 * WebApi constructor.
	 * @param RequestInterface $request
	 * @throws com\Lib\Err\BaseException\Throw_
	 */
	public function __construct( RequestInterface $request ) {
		$this->request = $request;
		// 构建api请求对象
		parent::__construct( $this->buildApiRequest() );
	}

	public function getHttpRequest():RequestInterface {
		return $this->request;
	}

	/**
	 * 构架api请求对象（ApiRequest）
	 * @return nameGateway\ApiRequest api请求对象
	 * @throws
	 */
	private function buildApiRequest(  ):nameGateway\ApiRequest {
		// 判断是否为调试模式
		$mode = $this->request->query( 'mode' );
		if( $mode === 'test' ){
			// throw com\Lib\Err\Exception::makeOfNew( '暂未支持测试模式', com\Lib\Err\Code::$apiSysParamError );
			if( com\Lib\Debug::runEnvIsLocal() ){
				return $this->buildApiRequestOfTestData();
			}else{
				throw com\Lib\Err\Exception::makeOfNew( '调试模式只允许在本地环境或测试环境中使用', com\Lib\Err\Code::$apiSysParamError );
			}
		}else{
			return $this->buildApiRequestOfDefault();
		}
	}

	/**
	 * @return nameGateway\ApiRequest
	 * @throws
	 */
	private function buildApiRequestOfDefault(  ):nameGateway\ApiRequest {
		// 取header参数
		$paramAsHeader = $this->request->getHeaders();
		// 取api参数
		if( $this->request->isMethod( 'GET' ) ){
			$apiParam = $this->request->query();
			// @todo 下划线转多维数组（时间关系，暂不实现），如：page_currentNum 转为 ['page']['currentNum']
		}else if( $this->request->isMethod( 'POST' ) ){
			$apiParam = $this->request->post();
		}else{
			throw com\Lib\Err\Exception::makeOfNew( 'api仅支持GET、POST请求', com\Lib\Err\Code::$apiSysParamError );
		}
		$apiRequest = new nameGateway\ApiRequest();
		// 设置api
		$apiRequest->apiData()->setApi( $this->getApiNameAsUrl() );
		// 设置调用信息
		$apiRequest->apiData()->setVersion( $paramAsHeader['api-version'][0] ?? nameGateway\ApiRequest\ApiData::$varDefaultVersion );
		$apiRequest->apiData()->setAccessToken( $paramAsHeader['access-token'][0] ?? '' );
		$apiRequest->apiData()->setTimestamp( $paramAsHeader['timestamp'][0] ?? 0 );
		$apiRequest->apiData()->setRequestId( $paramAsHeader['request_id'][0] ?? '' );
		$apiRequest->apiData()->setSign( $paramAsHeader['sign'][0] ?? '' );
		$apiRequest->apiData()->setSignType( $paramAsHeader['sign-type'][0] ?? nameGateway\ApiRequest\ApiData::$varDefaultSignType );
		// 是否为多参数模式
		if( ! com\Lib\Fun\Array_::arrayIsList( $apiParam ) ){
			// 单参数模式
			$apiRequest->apiData()->apiParam()->set( $apiParam );
		}else{
			// 多参数模式
			$apiRequest->apiData()->setApiParams( $apiParam );
			// 多参数模式下是否独立响应每个参数
			if( isset( $paramAsHeader['isIndependentRes'][0] ) ){
				$apiRequest->apiData()->set( 'isIndependentRes', $paramAsHeader['isIndependentRes'][0] );
			}
		}
		//
		return $apiRequest;
	}

	/**
	 * 构架api请求对象（测试数据）（ApiRequest）
	 * @return nameGateway\ApiRequest api请求对象
	 * @throws
	 */
	private function buildApiRequestOfTestData(  ):nameGateway\ApiRequest {
		// 取header参数
		// $paramAsHeader = $this->request->getHeaders();
		// 自动申请token，注意：670b1b4a9b01f5948c900dfe6b2596f59a45c4fce30062accfca5fc25f9adf11为调试模式用
		$tokenObj = new com\Cla\Com\Token( '670b1b4a9b01f5948c900dfe6b2596f59a45c4fce30062accfca5fc25f9adf11' );
		if( ! $tokenObj->isValid() ){
			$tokenObj = com\Cla\Com\Token::apply( [ 'token' => $tokenObj->getAccessToken() ] );
			//
			$tokenObj->session()->setOfPath( 'isDebugUser', 1 );
			// 增加权限
			$tokenObj->auth()->addRuleOfAuthNameLeftMatch( '*' );
		}
		//
		$paramAsHeader['api-version'][0] = $tokenObj->getAccessToken();
		// 装载api请求数据
		$apiRequest = $this->buildApiRequestOfDefault();
		// 生成签名
		$apiRequest->apiData()->setSign( $apiRequest->sign()->buildSign() );
		//
		return $apiRequest;
	}

	/**
	 * 获取api名
	 * @return string
	 */
	private function getApiNameAsUrl():string {
		// 取"api/"后面的url
		$apiPrefix = substr( $this->request->getPathInfo(), 4 );
		// 将"/"替换为"."
		$apiPrefix = str_replace( '/', '.', $apiPrefix );
		//
		$apiPrefix = str_replace( '-', '_', $apiPrefix );
		// 转为小驼峰
		$apiPrefix = com\Lib\Fun\Str::parseName( $apiPrefix, 1, false );
		//
		return ltrim( $apiPrefix, '.' );
	}

}
